1.10. Чтение и запись
Чтение и запись
★ Чтение и запись данных – процедуры информационного обмена с источником данных. В этом «обмене» нужно запомнить несколько ключевых концепций – собственно, чтение и запись, а также указатель файла, буферизация и системные вызовы.
Операционная система рассматривает файл как линейную последовательность байтов, каждый из которых имеет свой номер (offset), начиная с 0. Допустим, файл Привет.txt содержит текст «Hello»:
| Байт | 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| Символ | H | e | l | l | o |
В том же «Hello» спрятан интересный процесс кодировки – физически это набор сигналов, сгруппированных как файл, состоящий из байтов, а мы видим вполне себе текстовую часть – это происходит за счёт декодирования в установленной кодировке. Но как система понимает, в каком месте «e», допустим? Вот именно для этого и используется специальная переменная, которая называется указатель файла (file pointer/file descriptor position), хранящий текущую позицию в файле (номер байта, с которого начнётся следующая операция).
Это работает так:
- файл открывается → указатель останавливается на первом – 0;
- после каждой операции чтения/записи он автоматически сдвигается на количество обработанных байтов;
- программа может вручную изменить позицию указателя (прочитать данные из середины файла);
- файл можно открыть в разных программах, и указатель будет везде свой.
То есть, файлы – байтовые потоки данных, а указатель – «курсор», который двигается при чтении/записи. И когда программа читает файл, данные проходят некую «расшифровку» из формата хранения в язык запроса – при этом выполняется два этапа:
- системный буфер (кэш ОС), когда данные копируются с диска в память ядра, а если следующему запросу понадобятся те же данные, они берутся не с диска, а с ядра, что ускоряет работу, словно «ящик около стола» вместо «хождения в архив»;
- прикладной буфер (буфер программы), когда данные копируются из системного буфера в память программы.
Сложно? Давайте проще – если программа дважды читает один и тот же участок файла, второй запрос будет мгновенным – данные уже в системном буфере. Это и есть буферизация – помещение данных в буфер, чтобы «не бегать в архив», такой метод организации обмена ввода и вывода данных, который использует буфер для временного хранения данных, читая данные «порционно».
Файлы — это данные, которые хранятся на носителях: жёстких дисках (HDD), SSD, флешках и прочих. Но для удобства работы с ними операционная система использует файловую систему — специальную структуру, которая управляет тем, где, как и в каком порядке записываются данные.
Файловая система управляет хранением данных, следит за тем, какие части диска заняты, а какие свободны, хранит метаданные о файлах (имя, размер, дата создания, права доступа), и организует их в каталоги и папки. Данные расположены в древовидной иерархии, где всегда есть первый уровень - корень, и дочерние элементы - каталоги. Каталоги могут содержать в себе файлы и другие каталоги, что и порождает пути:
Корень/Каталог/Каталог/Каталог/Файл
Каждый файл и папка имеет свой уникальный путь от корня /.
В Linux и macOS каждому файлу присваивается inode — уникальный номер, который содержит информацию о правах, владельце, времени изменения, указателях на физические блоки на диске. Путь не определяет inode напрямую, но используется как ссылка на него через имена файлов и каталогов. Система ищет начиная с корня, и поэтапно идёт по элементам в адресе.
Путь — это способ указать местоположение файла или папки в иерархии файловой системы. Он похож на адрес вроде «улица Ленина, дом 5». Путь может быть абсолютным и относительным.
Абсолютный путь является полным, начиная от корневой директории файловой системы или диска, всегда однозначный и не зависит от текущего рабочего каталога программы. Примеры:
Windows - C:\Users\Timur\Documents\file.txt
Linux/macOS - /home/timur/Documents/file.txt
Такой путь всегда начинается от корня (/ в Unix-системах, C:\ в Windows) и точно указывает, где находится файл.
Относительный путь является путём относительно текущего рабочего каталога. Он короче и зависит от того, в какой директории работает (запущено) приложение:
Documents/file.txt
../Downloads/file.txt
Когда программа запускается, у неё есть текущий рабочий каталог — это место, от которого будут считаться относительные пути.